#!/usr/bin/env bash
# group: rw
#
# Test encryption key management with luks
# Based on 134
#
# Copyright (C) 2019 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# creator
owner=mlevitsk@redhat.com

seq=`basename $0`
echo "QA output created by $seq"

status=1	# failure is the default!

_cleanup()
{
	_cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15

# get standard environment, filters and checks
. ./common.rc
. ./common.filter

_supported_fmt qcow2 luks
_supported_proto file fuse #TODO
_require_working_luks

QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT

if [ "$IMGFMT" = "qcow2" ] ; then
	PR="encrypt."
	EXTRA_IMG_ARGS="-o encrypt.format=luks"
fi


# secrets: you are supposed to see the password as *******, see :-)
S0="--object secret,id=sec0,data=hunter0"
S1="--object secret,id=sec1,data=hunter1"
S2="--object secret,id=sec2,data=hunter2"
S3="--object secret,id=sec3,data=hunter3"
S4="--object secret,id=sec4,data=hunter4"
SECRETS="$S0 $S1 $S2 $S3 $S4"

# image with given secret
IMGS0="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec0"
IMGS1="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec1"
IMGS2="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec2"
IMGS3="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec3"
IMGS4="--image-opts driver=$IMGFMT,file.filename=$TEST_IMG,${PR}key-secret=sec4"


echo "== creating a test image =="
_make_test_img $S0 $EXTRA_IMG_ARGS -o ${PR}key-secret=sec0,${PR}iter-time=10 32M

echo
echo "== test that key 0 opens the image =="
$QEMU_IO $S0 -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir

echo
echo "== adding a password to slot 4 =="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec4,${PR}iter-time=10,${PR}keyslot=4
echo "== adding a password to slot 1 =="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10
echo "== adding a password to slot 3 =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10,${PR}keyslot=3

echo "== adding a password to slot 2 =="
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10


echo "== erase slot 4 =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=4 | _filter_img_create


echo
echo "== all secrets should work =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done

echo
echo "== erase slot 0 and try it =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 | _filter_img_create
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS0 | _filter_qemu_io | _filter_testdir

echo
echo "== erase slot 2 and try it =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=2 | _filter_img_create
$QEMU_IO $SECRETS -c "read 0 4096" $IMGS2 | _filter_qemu_io | _filter_testdir


# at this point slots 1 and 3 should be active

echo
echo "== filling  4 slots with secret 2 =="
for ((i = 0; i < 4; i++)); do
	$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec2,${PR}iter-time=10
done

echo
echo "== adding secret 0 =="
	$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10

echo
echo "== adding secret 3 (last slot) =="
	$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10

echo
echo "== trying to add another slot (should fail) =="
$QEMU_IMG amend $SECRETS $IMGS2 -o ${PR}state=active,${PR}new-secret=sec3,${PR}iter-time=10

echo
echo "== all secrets should work again =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done


echo

echo "== erase all keys of secret 2=="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec2

echo "== erase all keys of secret 1=="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1

echo "== erase all keys of secret 0=="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec0

echo "== erasing secret3 will fail now since it is the only secret (in 3 slots) =="
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=inactive,${PR}old-secret=sec3

echo
echo "== only secret3 should work now  =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done

echo
echo "== add secret0  =="
$QEMU_IMG amend $SECRETS $IMGS3 -o ${PR}state=active,${PR}new-secret=sec0,${PR}iter-time=10

echo "== erase secret3 =="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=inactive,${PR}old-secret=sec3

echo
echo "== only secret0 should work now  =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done

echo
echo "== replace secret0 with secret1 (should fail)  =="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}keyslot=0

echo
echo "== replace secret0 with secret1 with force (should work)  =="
$QEMU_IMG amend $SECRETS $IMGS0 -o ${PR}state=active,${PR}new-secret=sec1,${PR}iter-time=10,${PR}keyslot=0 --force

echo
echo "== only secret1 should work now  =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done


echo
echo "== erase last secret (should fail)  =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec1


echo "== erase non existing secrets (should fail)  =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec5 --force
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}old-secret=sec0 --force
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=1 --force

echo
echo "== erase last secret with force by slot (should work)  =="
$QEMU_IMG amend $SECRETS $IMGS1 -o ${PR}state=inactive,${PR}keyslot=0 --force

echo
echo "== we have no secrets now, data is lost forever =="
for IMG in "$IMGS0" "$IMGS1" "$IMGS2" "$IMGS3"; do
	$QEMU_IO $SECRETS -c "read 0 4096" $IMG | _filter_qemu_io | _filter_testdir
done

# success, all done
echo "*** done"
rm -f $seq.full
status=0

